package com.zjl.学习.第03章_步骤Shop.C1_居于块Tasklet;

import com.zjl.springbatch.util.OutColour;
import org.springframework.batch.core.*;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.scope.context.*;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.item.*;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;

/**
 * 居于块的 Tasklet 相对简单Tasklet来说，多了3个模块：
 *      ItemReader( 读模块)，
 *      ItemProcessor(处理模块)，
 *      ItemWriter(写模块)，
 *  跟它们名字一样， 一个负责数据读， 一个负责数据加工，一个负责数据写。
 *
 * 看时序图可知，一个  ChunkTasklet(居于块的 Tasklet) 中可以多次读和多次加工处理，但是只有一个写
 *
 */
@SpringBootApplication
@EnableBatchProcessing//开启spring batch
public class C1_居于块Tasklet {

    public static void main(String[] args) {
//        args = new String[]{"name=张蛟龙3"};//模拟 入参
        System.setProperty("spring.profiles.active","01");//  同理 --spring.profiles.active=xxx

        SpringApplication.run(C1_居于块Tasklet.class, args);
        System.out.println("***********启动完毕**当前编码:" + Charset.defaultCharset().name() + "****************");

    }
    @Autowired//@EnableBatchProcessing 这个注解帮你从 spring batch 的配置文件中加载了
    private JobLauncher jobLauncher;//Job 启动器
    @Autowired//Job 构造工厂
    private JobBuilderFactory jobBuilderFactory;
    @Autowired//构建 Step
    private StepBuilderFactory stepBuilderFactory;

    @Bean
    public Step step003() throws Exception {

        return stepBuilderFactory.get("step003")
                .<Object,String>chunk(3)  //设置块的size为3次,即 reader 和 processor 执行三次再执行 writer
                .reader(itemReader()).reader(itemReader())//设置多次读写无意义，只会执行 最后一次，都是覆盖操作
                .processor(itemProcessor())
                .writer(itemWriter())
                .build();
    }
    /**
     * 如果 .chunk(3)//设置块的size为3次,即 reader 和 processor 执行三次再执行 writer
     * 程序一直在循环打印，先循环打印3次reader， 再循环打印3次processor，最后一次性输出3个值。
     *      其实这个是 ChunkTasklet 执行特点，ItemReader会一直循环读，直到返回 null ，才停止。
     *      而processor也是一样，itemReader读多少次，它处理多少次，
     *      itemWriter 一次性输出当前次输入的所有数据。
     *
     * 如果 执行次数到第二次就返回 null 了，那么也会终止读
     */
    int k = 4;
    @Bean
    public ItemReader<Object> itemReader(){
        return new ItemReader<Object>() {
            @Override //读取数据 并返回
            public Object read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
                OutColour.out.printlnRed("-------------read------------>");
                if(k-- > 0){
                    return "read-ret" + k;
                }else{
                    return null;
                }

            }
        };
    }

    @Bean//             入参      出参
    public ItemProcessor<Object,String> itemProcessor(){
        return new ItemProcessor<Object,String>() {
            @Override //返回给处理数据   处理后并返回  如果读返回的结果是 null 则会不进入，不处理
            public String process(Object item) throws Exception {
                OutColour.out.printlnRed("-------------process---------->" + item);
                return "process-ret->" + item;
            }
        };
    }
    @Bean
    public ItemWriter<String> itemWriter(){
        return new ItemWriter<String>() {
            @Override//将返回的数据  惊醒继续操作
            public void write(List items) throws Exception {
                OutColour.out.printlnRed("-------------write----------->" + items);
            }
        };
    }
    @Bean// 会自己找 指定符合的类传进去入参
    public Job job003() throws Exception {
        return jobBuilderFactory.get("job003")
                .start(step003())
                .incrementer(new RunIdIncrementer())
                .build();
    }

}
